//
// Created by  ta&to on 2022/10/9.
//
#include "tcp_handler.h"

log_t global_logt;
thread_pool_t global_tpt;
tcp_pool_t global_tcp;
void _init_tcp() {
    pthread_mutex_init(&global_tcp.tcp_mut_lock, NULL);
    pthread_rwlock_init(&global_tcp.tcp_rw_lock, NULL);
}

static void _after_request_cycle(void *args, thread_task_args_t *args_t){
    tcp_inner_request_after_facade_t *hirqaft = (tcp_inner_request_after_facade_t *)args;
    int status = TCP_SOCKET_OPEN;
    while(status == TCP_SOCKET_OPEN) {
        noder node = RBtreenodesel(hirqaft->hset->srdc->req_data, &hirqaft->fd);
        if(ISNOTNULL(node)) {
            struct Queue *queue = ((struct Queue*)node->spot->value);
            if(ISNOTNULL(queue)){
                tcp_inner_req_status_pkg_t *pkg = ( tcp_inner_req_status_pkg_t *)popTaskBlock(queue);
                if(ISNOTNULL(pkg)) {
                    switch (pkg->status) {
                        case TCP_SOCKET_OPEN: {
                            control_tcp_pkg(hirqaft->hset, pkg);
                            tcp_free(pkg);                                                      // 回收包
                            break;
                        }
                        case TCP_SOCKET_CLOSE: {
                            info(hirqaft->logs, "Exit(%d)", hirqaft->fd);
                            RBtreenodedel(hirqaft->hset->srdc->req_data, &hirqaft->fd); // 删掉容器中的队列
                            Close_Client(hirqaft->hset->logs, hirqaft->hset, hirqaft->fd);
                            tcp_free(pkg);                                             // 回收包
                            tcp_free(queue);                                           // 回收队列资源
                            tcp_free(hirqaft);                                         // 回收容器资源
                            return;
                        }
                    }
                }
            }
        }
    }
}
static void _request_do(struct tcp_socket_event_loop_s *hset, int fd, int status){
    tcp_inner_req_status_pkg_t *pkg = (tcp_inner_req_status_pkg_t *)tcp_malloc(sizeof(tcp_inner_req_status_pkg_t));
    noder node = RBtreenodesel(hset->srdc->req_data, &fd);
    hset->hcontxt->fd = fd;
    pkg->fd = fd;
    if(ISNULL(node)) {
        tcp_inner_request_after_facade_t *hirqaft = (tcp_inner_request_after_facade_t *)tcp_malloc(sizeof(tcp_inner_request_after_facade_t));
        struct Queue* queue = (struct Queue*) tcp_malloc(sizeof(struct Queue));
        initQueue(queue, 100);
        hirqaft->fd = hset->hcontxt->fd;
        hirqaft->status = status;
        hirqaft->hset = hset;
        hirqaft->logs = hset->logs;
        RBtreenodeadd(hset->srdc->req_data, &fd, queue);
        Thread_Task_Post(&global_tpt, _after_request_cycle, hirqaft);
    }
    node = RBtreenodesel(hset->srdc->req_data, &fd);
    if(ISNOTNULL(node)) {
        switch (status) {
            case TCP_SOCKET_OPEN: {
                pkg->status = TCP_SOCKET_OPEN;
                pkg->data = dtsnew(hset->func_handler->data);
                break;
            }
            case TCP_SOCKET_CLOSE: {
                pkg->status = TCP_SOCKET_CLOSE;
                pkg->data = dtsnew("closed");
                break;
            }
        }
        task_push((struct Queue*)node->spot->value, pkg);        // 向队列中推送头部信息
    }
}
static void _before_request_cycle(void *args, thread_task_args_t *args_t) {
    tcp_inner_request_before_facade_t *hirqbft = (tcp_inner_request_before_facade_t *)args;

    int ret,fd = hirqbft->fd;
    struct tcp_socket_event_loop_s *hset = hirqbft->hset;
    tcp_free(hirqbft);                                     // 回收容器
    do{
        ret = getData(hset->logs, fd, hset->func_handler->data,hset->func_handler->data_len - 1);
        //如果客户端主动断开连接，会进行四次挥手，会出发一个信号，此时相应的套接字会有数据返回，告诉select，我的客户断开了，你返回-1
        if(ret <=0) //客户端连接关闭，清除文件描述符集中的相应的位
        {
            debug(hset->logs, "client[%d] be going to close\n", fd);
            _request_do(hset, fd, TCP_SOCKET_CLOSE);
            return;         // 任务结束
        } else {//否则有相应的数据发送过来 ，进行相应的处理
            if(ret < hset->func_handler->data_len)
                memset(&hset->func_handler->data[ret],'\0',1);
            _request_do(hset, fd, TCP_SOCKET_OPEN);
        }
    } while (ret > 0);
}
#ifdef SOCKET_SERVER_SELECT
void _tcp_socket_callback(struct tcp_socket_event_loop_s *hset, int fd, int n) {
#else
void _tcp_socket_callback(struct tcp_socket_event_loop_s *hset, int fd) {
#endif
    tcp_inner_request_before_facade_t *hirqbft = (tcp_inner_request_before_facade_t *)malloc(sizeof(tcp_inner_request_before_facade_t));
#ifdef SOCKET_SERVER_SELECT
    hirqbft->n = n;
#endif
    hirqbft->fd = fd;
    hirqbft->hset = hset;
    Thread_Task_Post(&global_tpt, _before_request_cycle, hirqbft);
}